package org.jeecg.modules.activiti.service.Impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.IdUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.google.common.collect.Maps;
import org.activiti.bpmn.model.Process;
import org.activiti.bpmn.model.*;
import org.activiti.engine.IdentityService;
import org.activiti.engine.RepositoryService;
import org.activiti.engine.RuntimeService;
import org.activiti.engine.TaskService;
import org.activiti.engine.impl.RepositoryServiceImpl;
import org.activiti.engine.impl.persistence.entity.ProcessDefinitionEntity;
import org.activiti.engine.impl.pvm.PvmActivity;
import org.activiti.engine.impl.pvm.PvmTransition;
import org.activiti.engine.impl.pvm.process.ActivityImpl;
import org.activiti.engine.impl.task.TaskDefinition;
import org.activiti.engine.runtime.ProcessInstance;
import org.activiti.engine.task.Task;
import org.apache.commons.lang.StringUtils;
import org.apache.shiro.SecurityUtils;
import org.jeecg.common.api.dto.message.BusMessageDTO;
import org.jeecg.common.exception.JeecgBootException;
import org.jeecg.common.system.api.ISysBaseAPI;
import org.jeecg.common.system.vo.LoginUser;
import org.jeecg.common.util.DateUtils;
import org.jeecg.common.util.EmptyUtil;
import org.jeecg.common.util.SpringContextUtils;
import org.jeecg.modules.activiti.entity.*;
import org.jeecg.modules.activiti.enums.ActNodeEnum;
import org.jeecg.modules.activiti.mapper.ActZprocessMapper;
import org.jeecg.modules.activiti.service.IActZTaskService;
import org.jeecg.modules.activiti.service.IActZVariableService;
import org.jeecg.modules.activiti.service.IActZprocessService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.mail.SimpleMailMessage;
import org.springframework.mail.javamail.JavaMailSender;
import org.springframework.stereotype.Service;

import javax.persistence.EntityManager;
import javax.persistence.PersistenceContext;
import java.math.BigDecimal;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @Description: 流程定义扩展表
 * @Author: pmc
 * @Date:   2020-03-22
 * @Version: V1.0
 */
@Service
public class ActZprocessServiceImpl extends ServiceImpl<ActZprocessMapper, ActZprocess> implements IActZprocessService {
    @Autowired
    private RuntimeService runtimeService;

    @Autowired
    private IdentityService identityService;

    @Autowired
    private RepositoryService repositoryService;

    @Autowired
    private TaskService taskService;
    @Autowired
    private ActNodeServiceImpl actNodeService;
    @Autowired
    private ActBusinessServiceImpl actBusinessService;
    @PersistenceContext
    private EntityManager entityManager;
    @Autowired
    private ISysBaseAPI sysBaseAPI;
    @Autowired
    private ActZprocessMapper actZprocessMapper;


    // 流程变量配置表
    @Autowired
    private IActZVariableService actZVariableService;
    // 待办任务扩展表
    @Autowired
    private IActZTaskService actZTaskService;

    /**
     * 通过key设置所有版本为旧
     * @param processKey
     */
    public void setAllOldByProcessKey(String processKey) {
        List<ActZprocess> list = this.list(new LambdaQueryWrapper<ActZprocess>().eq(ActZprocess::getProcessKey,processKey));
        if(list==null||list.size()==0){
            return;
        }
        list.forEach(item -> {
            item.setLatest(false);
        });
        this.updateBatchById(list);
    }

    /**
     * 更新最新版本的流程
     * @param processKey
     */
    public void setLatestByProcessKey(String processKey) {
        ActZprocess actProcess = this.findTopByProcessKeyOrderByVersionDesc(processKey);
        if(actProcess==null){
            return;
        }
        actProcess.setLatest(true);
        this.updateById(actProcess);
    }

    private ActZprocess findTopByProcessKeyOrderByVersionDesc(String processKey) {
        List<ActZprocess> list = this.list(new LambdaQueryWrapper<ActZprocess>().eq(ActZprocess::getProcessKey, processKey)
                .orderByDesc(ActZprocess::getVersion)
        );
        if (CollUtil.isNotEmpty(list)){
            return list.get(0);
        }
        return null;
    }

    public String startProcess(ActBusiness actBusiness)  {
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        // 启动流程用户
        identityService.setAuthenticatedUserId(loginUser.getId());
        // 启动流程 需传入业务表id变量
        Map<String, Object> params = actBusiness.getParams();
        params.put("tableId", actBusiness.getTableId());

        String tableName = actBusiness.getTableName();
        String tableId = actBusiness.getTableId();

        /* 加载流程变量 */
/*        Map<String, Object> busiData = actBusinessService.getBusiData(tableId, tableName);
        for (String key : busiData.keySet()) {
            params.put(key,busiData.get(key));
        }*/
        // update-begin-Autor: Wengmf date: 2022-01-14 11:42 for: 获取流程变量，设置流程变量
        QueryWrapper<ActZVariable> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq("process_key", actBusiness.getProcessKey());
        List<ActZVariable> zVariableList = actZVariableService.list(queryWrapper);
        if (zVariableList.size() > 0) {
            // 获取表单数据
            Map<String, Object> busiData = actBusinessService.getBusiData(actBusiness.getTableId(), actBusiness.getTableName());
            for (ActZVariable zVariable : zVariableList) {
            /*    if (zVariable.getVarType() == 1 && StringUtils.isNotBlank(zVariable.getVarValue())) {
                    // JS脚本 -- 解析JS代码块
                    ScriptEngineManager manager = new ScriptEngineManager();
                    ScriptEngine engine = manager.getEngineByName("js");
                    String jsString = zVariable.getVarValue().replaceAll("or", "||");
                    jsString = jsString.replaceAll("and", "&&");
                    engine.put(zVariable.getVarName(), busiData.get(zVariable.getVarName()));
                    Object result = engine.eval(jsString);
                    params.put(zVariable.getVarName(),busiData.get(zVariable.getVarName()));
                } else {
                    // 表单值
                    params.put(zVariable.getVarName(),busiData.get(zVariable.getVarName()));
                }
                */
                params.put(zVariable.getVarName(),busiData.get(zVariable.getVarName()));
            }
        }

        // update-end-Autor: Wengmf date: 2022-01-14 11:42 for: 获取流程变量，设置流程变量

        ProcessInstance pi = runtimeService.startProcessInstanceById(actBusiness.getProcDefId(), actBusiness.getId(), params);
        // 设置流程实例名称
        runtimeService.setProcessInstanceName(pi.getId(), actBusiness.getTitle());
        List<Task> tasks = taskService.createTaskQuery().processInstanceId(pi.getId()).list();
        for(Task task : tasks){
            if(actBusiness.getFirstGateway()){
                // 网关类型
                List<LoginUser> users = getNode(task.getTaskDefinitionKey(),tableName,tableId,actBusiness.getProcDefId()).getUsers();
                // 如果下个节点未分配审批人为空 取消结束流程
                if(users==null||users.size()==0){
                    throw new RuntimeException("任务节点未分配任何候选审批人，发起流程失败");
                }else{
                    // 分配了节点负责人分发给全部
                    for(LoginUser user : users){
                        taskService.addCandidateUser(task.getId(), user.getId());
                        // 异步发消息
                        sendActMessage(loginUser,user,actBusiness,task.getName(), actBusiness.getSendMessage(),
                                actBusiness.getSendSms(), actBusiness.getSendEmail());
                    }
                }
            }else {
                // 分配第一个任务用户
                String assignees = actBusiness.getAssignees();
                actBusiness.setTaskId(task.getId());
                for (String assignee : assignees.split(",")) {
                    taskService.addCandidateUser(task.getId(), assignee);

                    // update-begin-Autor: Wengmf date: 2022-02-09 0:02 for: 添加自定义待办任务
                    ActZTask actZTask = new ActZTask();
                    actZTask.setSendId(assignee); // 发起人Id
                    actZTask.setSendName(loginUser.getRealname()); //发起人名称
                    actZTask.setOwnerId(assignee);//审批人名称
                    actZTask.setOwnerName(loginUser.getRealname()); //
                    actZTask.setState(0);//流程状态:0未提交,1审批中,2已完成,3已退回
                    actZTask.setTableId(actBusiness.getTableId());//单据id
                    actZTask.setTitle(actBusiness.getTitle());//流程标题
                    actZTask.setReceiveTime(new Date());//发送时间
                    actZTask.setProcessId(actBusiness.getProcDefId());//所属流程d
                    actZTask.setProcInstId(pi.getId());//流程实例id
                    actZTask.setNodeName(task.getName()); //任务节点名称
                    actZTask.setNodeState(0); //节点状态：0未处理1已处理
                    actZTask.setTaskId(task.getId()); //工作流任务id
                    actZTask.setRouteName(actBusiness.getRouteName()); //页面路由
                    actZTask.setUpdateTime(actZTask.getReceiveTime()); // 更新时间
                    actZTask.setSerial(1); // 序号-流水号
                    actZTaskService.save(actZTask);

                    // update-end-Autor: Wengmf date: 2022-02-09 0:02 for: 添加自定义待办任务

                    // 异步发消息
//                    LoginUser user = sysBaseAPI.getUserById(assignee);
//                    sendActMessage(loginUser,user,actBusiness,task.getName(), actBusiness.getSendMessage(),
//                            actBusiness.getSendSms(), actBusiness.getSendEmail());
                }
            }
            // 设置任务优先级
            taskService.setPriority(task.getId(), actBusiness.getPriority());
        }
        return pi.getId();
    }

    public Map<String,Object> startProcess(ActBusiness actBusiness,String type) {  //type:单据类型
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        // 启动流程用户
        identityService.setAuthenticatedUserId(loginUser.getId());
        // 启动流程 需传入业务表id变量
        Map<String, Object> params = actBusiness.getParams();
        params.put("tableId", actBusiness.getTableId());
        ActBusiness act = actBusinessService.getById(actBusiness.getId());
        String tableName = act.getTableName();
        String tableId = act.getTableId();
        if (StrUtil.isBlank(tableId)||StrUtil.isBlank(tableName)){
            throw new JeecgBootException("没有业务表单数据");
        }
        /*表单数据写入*/
        Map<String, Object> busiData = actBusinessService.getBusiData(tableId, tableName);
        //此对象作为流程变量（注意：POJO类型，一定要实现Serializable接口，否则在存储这个pojo时就会报异常）
        Map<String,Object> eaAmtMap = new HashMap<String,Object>();
        String userid = "e9ca23d68d884d4ebb19d07889727dae";   //报销人
        if(!EmptyUtil.checkNull(busiData.get("eaPersonId")).equals("")){
            userid = EmptyUtil.checkNull(busiData.get("eaPersonId"));
        }
        if(!EmptyUtil.checkNull(busiData.get("personId")).equals("")){
            userid = EmptyUtil.checkNull(busiData.get("personId"));
        }
        if(!EmptyUtil.checkNull(busiData.get("personalId")).equals("")){
            userid = EmptyUtil.checkNull(busiData.get("personalId"));
        }
        if(!EmptyUtil.checkNull(busiData.get("borrowerId")).equals("")){
            userid = EmptyUtil.checkNull(busiData.get("borrowerId"));
        }
        if(!EmptyUtil.checkNull(busiData.get("repayerId")).equals("")){
            userid = EmptyUtil.checkNull(busiData.get("repayerId"));
        }

        //要设置费用项目以及报销金额
        String indexId = EmptyUtil.checkNull(busiData.get("indexId"));    //费用项目

        BigDecimal actualPayAmt = new BigDecimal(0);    //实际付款金额
        if(busiData.get("actualPayAmt") != null){
            actualPayAmt = new BigDecimal(busiData.get("actualPayAmt").toString());
        }
        if(busiData.get("loan_amount") != null){
            actualPayAmt = new BigDecimal(busiData.get("loan_amount").toString());
        }

        //判断总经理审核还是董事长审核
        int needPresident = checkIsNeedPresidentAudit(indexId,actualPayAmt);
        int needCeo = checkIsNeedCeoAudit(indexId,actualPayAmt);
        int needAg = 0;
        int needCfo = 0;  // 财务领导审批

        //费用承担部门
        String costDeptId2 = "";
        if(!EmptyUtil.checkNull(busiData.get("paymentDeptId")).equals("")){
            costDeptId2 = EmptyUtil.checkNull(busiData.get("paymentDeptId"));
        }
        if(!EmptyUtil.checkNull(busiData.get("costDept")).equals("")){
            costDeptId2 = EmptyUtil.checkNull(busiData.get("costDept"));
        }
        String costDeptId = costDeptId2;
        String costDeptName = sysBaseAPI.getDepartNameById(costDeptId);

        //判断是否高管
        int toDeptManager = 0;  // 分管领导节点
        int toPresident = 0;    // 董事长节点
        int toCeo = 0;  // 总经理节点
        int toAg = 0;   // 总会计师节点



        // 招待费申请单节点判断（总经理、总会计师；【条件：预算费用大于等于2000】）
        if("ea_entertain_apply".equals(tableName)){
            // 招待费申请单的预算金额
            BigDecimal amount = new BigDecimal(busiData.get("amount").toString());
            // 标准金额 2000
            BigDecimal standardMoney = new BigDecimal(2000);
            if(amount.compareTo(standardMoney) == 1 || amount.compareTo(standardMoney) == 0){
                needAg = 1;
                toAg = 1;
            }
        }


        // 借款单、出差申请单 高管审批节点判断
        if("ea_business_apply".equals(tableName) || "ea_loanbill".equals(tableName) || "ea_payment".equals(tableName) || "ea_business_apply_change".equals(tableName)){
            // 通过部门名称判断走哪个节点
            if(costDeptName.equals("总经理室")){  //总经理审批
                toPresident = 1;
            }else if(costDeptName.equals("董事长室") || costDeptName.equals("副总经理室") || costDeptName.equals("总会计师室")){  //董事长室,总会计师室,副总经理室
                toCeo = 1;
            }else{
                toDeptManager = 1;
            }
        }

        // 差旅费报销单 高管审批节点判断 【如果总经理室、董事长室先走财务领导审批】
        if("ea_travel".equals(tableName)){
            // 通过部门名称判断走哪个节点
            if(costDeptName.equals("总经理室") || costDeptName.equals("董事长室")){  // 财务领导审批
                needCfo = 1;
            }else if(costDeptName.equals("副总经理室") || costDeptName.equals("总会计师室")){  //董事长室,总会计师室,副总经理室
                toCeo = 1;
            }else{
                toDeptManager = 1;
            }
        }
        if("ea_travel".equals(tableName) && needCfo == 1){
            if(costDeptName.equals("总经理室")){  //总经理审批
                needPresident = 1;
            }else if(costDeptName.equals("董事长室")){  //董事长室,总会计师室,副总经理室
                needCeo = 1;
            }
        }

        // 通过人员主键查询用户
        LoginUser loginUser1 = sysBaseAPI.getLoginUserByPkpsndoc(userid);
//        LoginUser loginUser1 = sysBaseAPI.getUserById(userid);
        //String createBy = EmptyUtil.checkNull(busiData.get("createBy"));   //获取第一个节点用户
        LoginUser loginUser2 = sysBaseAPI.getUserById(EmptyUtil.checkNull(busiData.get("createBy")));
        String createBy = EmptyUtil.checkNull(loginUser2.getId());



        eaAmtMap.put("identity",loginUser1.getUserIdentity());
        for (String key : busiData.keySet()) {
            params.put(key,busiData.get(key));
            params.put("user",eaAmtMap);  //报销用户信息
            params.put("needCfo",needCfo);   // 需要财务领导审批
            params.put("needPresident",needPresident);   //是否需要总经理审核
            params.put("needCeo",needCeo);   //是否需要董事长审核
            params.put("toDeptManager",toDeptManager);   //是否高管流程-部门负责人
            params.put("toPresident",toPresident);   //是否高管流程-董事长
            params.put("toCeo",toCeo);   //是否高管流程-总经理
            params.put("costDeptName",costDeptName);   //费用承担部门
            params.put("amt",actualPayAmt);   //实际报销金额
            params.put("indexId",indexId);   //费用项目
            params.put("needAg",needAg);   // 是否需要总会计师审批
            params.put("toAg",toAg);   // 总会计师审批
        }

        // 载入表单数据 设置流程变量
        ProcessInstance pi = runtimeService.startProcessInstanceById(actBusiness.getProcDefId(), actBusiness.getId(), params);
        // 设置流程实例名称
        runtimeService.setProcessInstanceName(pi.getId(), actBusiness.getTitle());
        List<Task> tasks = taskService.createTaskQuery().processInstanceId(pi.getId()).list();
        for(Task task : tasks){
            if(actBusiness.getFirstGateway()){
                // 网关类型
                List<LoginUser> users = getNode(task.getTaskDefinitionKey(),tableName,tableId,task.getProcessDefinitionId()).getUsers();
                // 如果下个节点未分配审批人为空 取消结束流程
                if(users==null||users.size()==0){
                    throw new RuntimeException("任务节点未分配任何候选审批人，发起流程失败");
                }else{
                    // 分配了节点负责人分发给全部
                    for(LoginUser user : users){
                        taskService.addCandidateUser(task.getId(), user.getId());
                        // 异步发消息
//                        sendActMessage(loginUser,user,actBusiness,task.getName(), actBusiness.getSendMessage(),
//                                actBusiness.getSendSms(), actBusiness.getSendEmail());
                    }
                }
            }else {
                // 分配第一个任务用户
                String assignees = createBy;
                for (String assignee : assignees.split(",")) {
                    taskService.addCandidateUser(task.getId(), assignee);
                    // 异步发消息
//                    LoginUser user = sysBaseAPI.getUserByName(assignee);
                    LoginUser user = sysBaseAPI.getUserById(assignee);
//                    sendActMessage(loginUser,user,actBusiness,task.getName(), actBusiness.getSendMessage(),
//                            actBusiness.getSendSms(), actBusiness.getSendEmail());
                }
            }
            // 设置任务优先级
            taskService.setPriority(task.getId(), actBusiness.getPriority());
            taskService.setVariable(task.getId(),"audit","2");
        }

        String workflowTaskId = "";
        for (int i = 0; i < tasks.size(); i++) {
            if(workflowTaskId.equals("")){
                workflowTaskId = tasks.get(i).getId();
            }else{
                workflowTaskId = workflowTaskId + "," + tasks.get(i).getId();
            }
        }

        Map<String,Object> returnMap = new HashMap<String,Object>();
        returnMap.put("piId",pi.getId());
        returnMap.put("workflowTaskId",workflowTaskId);
        return returnMap;
    }

    //判断是否需要总经理审核
    private int checkIsNeedCeoAudit(String indexId, BigDecimal actualPayAmt) {
        //费用项目：1412241467056876666  重大项目投资 并且报销金额大于2000000
        if(indexId.equals("1412241467056876666") && actualPayAmt.compareTo(new BigDecimal(2000000)) > 0){
            return 1;
        }
        //费用项目：1412246020229718018 资产处置支出 并且报销金额大于500000
        if(indexId.equals("1412246020229718018") && actualPayAmt.compareTo(new BigDecimal(500000)) > 0){
            return 1;
        }
        //费用项目：1412245689290743810 购置固定资产 并且报销金额大于10000
        if(indexId.equals("1412245689290743810") && actualPayAmt.compareTo(new BigDecimal(10000)) > 0){
            return 1;
        }
        //费用项目：1412245791271051266 购置无形资产 并且报销金额大于1000000
        if(indexId.equals("1412245791271051266") && actualPayAmt.compareTo(new BigDecimal(1000000)) > 0){
            return 1;
        }
        //费用项目：1412246311364747266 税费支出、利息支出及银行手续费 并且报销金额大于50000
        if(indexId.equals("1412246311364747266") && actualPayAmt.compareTo(new BigDecimal(50000)) > 0){
            return 1;
        }
        //费用项目：1412246378582663169 购进非经营性小额资产、商品、耗材等 并且报销金额大于10000
        if(indexId.equals("1412246378582663169") && actualPayAmt.compareTo(new BigDecimal(10000)) > 0){
            return 1;
        }
        //费用项目：1412246438393438209 房屋建筑物等维修 并且报销金额大于5000000
        if(indexId.equals("1412246438393438209") && actualPayAmt.compareTo(new BigDecimal(10000)) > 0){
            return 1;
        }
        //1412246519851016193 日常经营资金往来
        if(indexId.equals("1412246519851016193")){
            return 1;
        }
        //1412241664721838081 业务招待费 2000
        if(indexId.equals("1412241664721838081") && actualPayAmt.compareTo(new BigDecimal(2000)) > 0){
            return 1;
        }
        //1412241599315861506 办公费 10000
        if(indexId.equals("1412241599315861506") && actualPayAmt.compareTo(new BigDecimal(10000)) > 0){
            return 1;
        }
        //1412244490797735938 聘请中介机构费 10000
        if(indexId.equals("1412244490797735938") && actualPayAmt.compareTo(new BigDecimal(10000)) > 0){
            return 1;
        }
        //1412245170367258625 咨询费 10000
        if(indexId.equals("1412245170367258625") && actualPayAmt.compareTo(new BigDecimal(10000)) > 0){
            return 1;
        }
        //1412245255691984898 党建工作经费 10000
        if(indexId.equals("1412245255691984898") && actualPayAmt.compareTo(new BigDecimal(10000)) > 0){
            return 1;
        }
        //1412245325988519938 安全生产费用 10000
        if(indexId.equals("1412245325988519938") && actualPayAmt.compareTo(new BigDecimal(10000)) > 0){
            return 1;
        }
        //1412241889926602753 运输费 30000
        if(indexId.equals("1412241889926602753") && actualPayAmt.compareTo(new BigDecimal(30000)) > 0){
            return 1;
        }
        //1412242044197298177 装卸费 30000
        if(indexId.equals("1412242044197298177") && actualPayAmt.compareTo(new BigDecimal(30000)) > 0){
            return 1;
        }
        //1412242114913263618 仓储保管费 30000
        if(indexId.equals("1412242114913263618") && actualPayAmt.compareTo(new BigDecimal(30000)) > 0){
            return 1;
        }
        //1412242421936316418 广告宣传费 30000
        if(indexId.equals("1412242421936316418") && actualPayAmt.compareTo(new BigDecimal(30000)) > 0){
            return 1;
        }
        //1412242550663700481 业务经费 30000
        if(indexId.equals("1412242550663700481") && actualPayAmt.compareTo(new BigDecimal(30000)) > 0){
            return 1;
        }
        //1412242487245824002 销售服务费 30000
        if(indexId.equals("1412242487245824002") && actualPayAmt.compareTo(new BigDecimal(30000)) > 0){
            return 1;
        }
        //1412242785846714370 汽车费用 10000
        if(indexId.equals("1412242785846714370") && actualPayAmt.compareTo(new BigDecimal(10000)) > 0){
            return 1;
        }
        //1412244355074252801 水电费 10000
        if(indexId.equals("1412244355074252801") && actualPayAmt.compareTo(new BigDecimal(10000)) > 0){
            return 1;
        }
        //1412243022527094786 租赁费 100000
        if(indexId.equals("1412243022527094786") && actualPayAmt.compareTo(new BigDecimal(100000)) > 0){
            return 1;
        }
        //1412243804869648385 汽车燃料费 10000
        if(indexId.equals("1412243804869648385") && actualPayAmt.compareTo(new BigDecimal(10000)) > 0){
            return 1;
        }
        //1412241467056877777  车辆保险费 10000
        if(indexId.equals("1412241467056877777") && actualPayAmt.compareTo(new BigDecimal(10000)) > 0){
            return 1;
        }
        //1412243994875813890 通行费 10000
        if(indexId.equals("1412243994875813890") && actualPayAmt.compareTo(new BigDecimal(10000)) > 0){
            return 1;
        }
        //1412244045501063169 停车费 10000
        if(indexId.equals("1412244045501063169") && actualPayAmt.compareTo(new BigDecimal(10000)) > 0){
            return 1;
        }
        //1412244147024191490 车辆修理费 10000
        if(indexId.equals("1412244147024191490") && actualPayAmt.compareTo(new BigDecimal(10000)) > 0){
            return 1;
        }
        //1412244213071896577 车辆其他费用 10000
        if(indexId.equals("1412244213071896577") && actualPayAmt.compareTo(new BigDecimal(10000)) > 0){
            return 1;
        }
        //1412241825548230658 包装费 30000
        if(indexId.equals("1412241825548230658") && actualPayAmt.compareTo(new BigDecimal(30000)) > 0){
            return 1;
        }
        //1412246645520752641 其他 1000
        if(indexId.equals("1412246645520752641") && actualPayAmt.compareTo(new BigDecimal(1000)) > 0){
            return 1;
        }

        //购入可供出售金融资产(1412241467056878888)
        if(indexId.equals("1412241467056878888")){
            return 1;
        }
        //重大工程建设项目(1412245447111630849)
        if(indexId.equals("1412245447111630849")){
            return 1;
        }
        //重要设备和技术引进(1412245547313553409)
        if(indexId.equals("1412245547313553409")){
            return 1;
        }
        //涉及捐赠或赞助支出(1412245923496484866)
        if(indexId.equals("1412245923496484866")){
            return 1;
        }
        //长期股权投资(1412246125137649666)
        if(indexId.equals("1412246125137649666")){
            return 1;
        }
        //境外出差费用等支出(1412246231106740226)
        if(indexId.equals("1412246231106740226")){
            return 1;
        }
        //权属公司日常周转用借款 (1412246588109119490 )
        if(indexId.equals("1412246588109119490")){
            return 1;
        }
        // 会议费(1412241718190825474)
        if(indexId.equals("1412241718190825474")){
            return 1;
        }
        return 0;
    }

    //判断是否需要董事长审核
    private int checkIsNeedPresidentAudit(String indexId, BigDecimal actualPayAmt) {
        //权属公司日常周转用借款 (1412246588109119490 )
        if(indexId.equals("1412246588109119490")){
            return 1;
        }
        //1412241467056876666 重大项目投资 并且报销金额大于2000000
        if(indexId.equals("1412241467056876666") && actualPayAmt.compareTo(new BigDecimal(2000000)) > 0){
            return 1;
        }
        //1412245447111630849 重大工程建设项目 并且报销金额小于5000000
        if(indexId.equals("1412245447111630849") && actualPayAmt.compareTo(new BigDecimal(5000000)) < 0){
            return 1;
        }
        //1412245547313553409 重要设备和技术引进 并且报销金额小于5000000
        if(indexId.equals("1412245547313553409") && actualPayAmt.compareTo(new BigDecimal(5000000)) < 0){
            return 1;
        }
        //1412246020229718018 资产处置支出 并且报销金额小于500000
        if(indexId.equals("1412246020229718018") && actualPayAmt.compareTo(new BigDecimal(500000)) < 0){
            return 1;
        }
        //1412245689290743810 购置固定资产 并且报销金额小于2000000
        if(indexId.equals("1412245689290743810") && actualPayAmt.compareTo(new BigDecimal(2000000)) < 0){
            return 1;
        }
        //1412245791271051266 购置无形资产 并且报销金额小于1000000
        if(indexId.equals("1412245791271051266") && actualPayAmt.compareTo(new BigDecimal(1000000)) < 0){
            return 1;
        }
        //1412246311364747266 税费支出、利息支出及银行手续费 并且报销金额大于1000000
        if(indexId.equals("1412246311364747266") && actualPayAmt.compareTo(new BigDecimal(1000000)) > 0){
            return 1;
        }
        //购入可供出售金融资产(1412241467056878888)
        if(indexId.equals("1412241467056878888")){
            return 1;
        }
        //涉及捐赠或赞助支出(1412245923496484866)
        if(indexId.equals("1412245923496484866")){
            return 1;
        }
        //长期股权投资(1412246125137649666)
        if(indexId.equals("1412246125137649666")){
            return 1;
        }
        //境外出差费用等支出(1412246231106740226)
        if(indexId.equals("1412246231106740226")){
            return 1;
        }
        //1412246519851016193 日常经营资金往来
        if(indexId.equals("1412246519851016193")){
            return 1;
        }
        return 0;
    }

    /**
     * 发送流程信息
     * @param fromUser 发送人
     * @param toUser 接收人
     * @param act 流程
     * @param taskName
     * @param sendMessage 系统消息
     * @param sendSms 短信消息
     * @param sendEmail 邮件消息
     */
    public void sendActMessage(LoginUser fromUser, LoginUser toUser, ActBusiness act, String taskName, Boolean sendMessage, Boolean sendSms, Boolean sendEmail) {
        String title = String.format("您有一个新的审批任务："+act.getTitle());
        Map<String, String> msgMap = Maps.newHashMap();
                        /*流程名称：  ${bpm_name}
催办任务：  ${bpm_task}
催办时间 :    ${datetime}
催办内容 :    ${remark}*/
        msgMap.put("bpm_name",act.getTitle());
        msgMap.put("bpm_task",taskName);
        msgMap.put("datetime", DateUtils.now());
        msgMap.put("remark", "请进入待办栏，尽快处理！");
        /*流程催办模板*/
        //String msgText = sysBaseAPI.parseTemplateByCode("bpm_cuiban", msgMap);
        String msgText = String.format("您有一个新的审批任务："+act.getTitle());
        this.sendMessage(act.getId(),fromUser,toUser,title,msgText,sendMessage,sendSms,sendEmail);

        //推送到指定的用户APP,进行弹窗提示

    }

    /**
     * 发消息
     * @param actBusId 流程业务id
     * @param fromUser 发送人
     * @param toUser 接收人
     * @param title 标题
     * @param msgText 信息内容
     * @param sendMessage 系统消息
     * @param sendSms 短信
     * @param sendEmail 邮件
     */
    public void sendMessage(String actBusId,LoginUser fromUser, LoginUser toUser,String title,String msgText,  Boolean sendMessage, Boolean sendSms, Boolean sendEmail) {
        if (sendMessage!=null&&sendMessage){
            BusMessageDTO messageDTO = new BusMessageDTO(fromUser.getUsername(),toUser.getUsername(),title,msgText,"2","bpm",actBusId);
            sysBaseAPI.sendBusAnnouncement(messageDTO);
        }
        //todo 以下需要购买阿里短信服务；设定邮件服务账号
        if (sendSms!=null&&sendSms&& StrUtil.isNotBlank(toUser.getPhone())){
            //DySmsHelper.sendSms(toUser.getPhone(), obj, DySmsEnum.REGISTER_TEMPLATE_CODE)
        }
        if (sendEmail!=null&&sendEmail&& StrUtil.isNotBlank(toUser.getEmail())){
            JavaMailSender mailSender = (JavaMailSender) SpringContextUtils.getBean("mailSender");
            SimpleMailMessage message = new SimpleMailMessage();
// 设置发送方邮箱地址
//            message.setFrom(emailFrom);
            message.setTo(toUser.getEmail());
            //message.setSubject(es_title);
            message.setText(msgText);
            mailSender.send(message);
        }
    }


    /**
     * 获取节点、节点审批人
     * @param nodeId
     * @param procDefId
     * @param busiData
     * @return
     */
    public ProcessNodeVo getNode(String nodeId,String procDefId,Map<String, Object> busiData) {

        ProcessNodeVo node = new ProcessNodeVo();
        // 设置关联用户
        List<LoginUser> users = getNodetUsers(nodeId,procDefId,busiData);
        node.setUsers(removeDuplicate(users));
        return node;
    }

    /**
     * 设置节点审批人
     * @param nodeId
     */
    public List<LoginUser> getNodetUsers(String nodeId,String procDefId,Map<String, Object> busiData){

        // update-begin-author: wmf data:2022-01-17 17:03 for: 获取节点参与人配置
        List<LoginUser> users = new ArrayList<>();
        List<ActNode> actNodes = actNodeService.findByNodeIdAndProcDefId(nodeId, procDefId);
        if (actNodes.size() > 0){
            ActNode actNode = actNodes.get(0);
            // 根据type 查对应的审批人
            ActNodeEnum tempEnum = ActNodeEnum.formCodeNode(actNode.getType());
            switch (tempEnum){
                case ROLE:
                    // update-begin-by wujinbiao 2022/3/10 17:29 for
//                    // 1、查询当前审批节点的角色信息
//                    List<ActNode> actNodeList = actNodeService.findByNodeIdAndProcDefId(nodeId, procDefId);
//                    if (actNodeList.size() > 0){
//                        ActNode actNode1 = actNodeList.get(0);
//                        String role = actNode1.getRelateId();
//                        if("ceo".equals(role)){// 总经理
//                            users = actNodeService.findCeoByOrgId((String) busiData.get("costCompCodeId"));
//                        }else if("fzjl".equals(role)){// 副总经理
//                            users = actNodeService.findFzjlByOrgId((String) busiData.get("costCompCodeId"));
//                        }else if ("zkjs".equals(role)){// 总会计师
//                            users = actNodeService.findZkjsByOrgId((String) busiData.get("costCompCodeId"));
//                        }else if ("CFO".equals(role)){// 财务领导
//                            users = actNodeService.findCwldByOrgId((String) busiData.get("costCompCodeId"));
//                        }else if ("finance".equals(role)){// 财务
//                            users = actNodeService.findCwByOrgId((String) busiData.get("costCompCodeId"));
//                        }else if ("president".equals(role)){// 董事长
//                            users = actNodeService.findDszByOrgId((String) busiData.get("costCompCodeId"));
//                        }else if ("zhbfzr".equals(role)){// 综合办公室
//                            users = actNodeService.findZhbgsByOrgId((String) busiData.get("costCompCodeId"));
//                        }
//                    }
//                    if(users.size() <= 0){
//                        // 根据角色去找人员
//                        users = actNodeService.findUsersByRole((String) busiData.get("costCompCodeId"), nodeId, procDefId);
//                    }
                    if(actNode != null){
                        // 当前组织
                        if(actNode.getOrgType() == 0){
                            users = actNodeService.findUsersByRole((String) busiData.get("costCompCodeId"), nodeId, procDefId);
                        // 其他组织
                        }else if(actNode.getOrgType() == 1){
                            users = actNodeService.findUsersByRole(actNode.getOrg(), nodeId, procDefId);
                        }
                    }
                    // update-end-by wujinbiao 2022/3/10 17:29 for
                    break;
                case COSTDEPTMANAGE:
                    //费用承担部门负责人
                    users = actNodeService.findUsersByCostDeptManage((String) busiData.get("costDept"));
                    break;
                case COSTDEPTLEADERS:
                    //费用承担分管领导
                    users = actNodeService.findUsersByCostDeptLeaders((String) busiData.get("costDept"));
                    break;
                case STARTER:
                    // 发起人
                    String createBy = (String) busiData.get("createBy");
                    LoginUser user = sysBaseAPI.getUserById(createBy);
                    users.add(user);
                    break;
                case STARTERDEPTMANAGER:
                    // 发起人的部门负责人
                    users = actNodeService.findUsersByCostDeptManage((String) busiData.get("deptId"));
                    break;
                case STARTERDEPTLEADERS:
                    // 发起人的部门分管领导
                    users = actNodeService.findUsersByCostDeptLeaders((String) busiData.get("deptId"));
                    break;
                case USER:
                    // 选择人员
                    users = actNodeService.findUserByNodeId(nodeId,procDefId);
                    break;
                default:
                    // 表单变量
                    break;
            }


        }

        // update-end-author: wmf

        // 过滤掉删除用户
//        users = users.stream().filter(u->StrUtil.equals("0",u.getDelFlag()+"")).collect(Collectors.toList());
        return users;
    }

    public ProcessNodeVo getNode(String nodeId,String tableName,String tableId,String procDefId) {

        ProcessNodeVo node = new ProcessNodeVo();
        // 设置关联用户
        List<LoginUser> users = getNodetUsers(nodeId,tableName,tableId,procDefId);
        node.setUsers(removeDuplicate(users));
        return node;
    }
    /**
     * 设置节点审批人
     * @param nodeId
     */
    public List<LoginUser> getNodetUsers(String nodeId,String tableName,String tableId,String procDefId){


        // 直接选择人员
        List<LoginUser> users = actNodeService.findUserByNodeId(nodeId,procDefId);
        // 根据角色选择
        List<Role> roles = actNodeService.findRoleByNodeId(nodeId,procDefId);
        for(Role r : roles){
            List<LoginUser> userList = actNodeService.findUserByRoleId(r.getId());
            users.addAll(userList);
        }
        // 部门
        List<Department> departments = actNodeService.findDepartmentByNodeId(nodeId,procDefId);
        for (Department d : departments){
            List<LoginUser> userList = actNodeService.findUserDepartmentId(d.getId());
            users.addAll(userList);
        }
        // 部门负责人
        List<Department> departmentManages = actNodeService.findDepartmentManageByNodeId(nodeId,procDefId);
        for (Department d : departmentManages){
            List<LoginUser> userList = actNodeService.findUserDepartmentManageId(d.getId());
            users.addAll(userList);
        }
        // 发起人部门负责人
        if(actNodeService.hasChooseDepHeader(nodeId,procDefId)){
            List<LoginUser> allUser = actNodeService.queryAllUser();
            /*表单数据写入*/
            Map<String, Object> busiData = actBusinessService.getBusiData(tableId, tableName);
            //费用承担部门
            String costDeptId2 = "";
            if(!EmptyUtil.checkNull(busiData.get("paymentDeptId")).equals("")){
                costDeptId2 = EmptyUtil.checkNull(busiData.get("paymentDeptId"));
            }
            if(!EmptyUtil.checkNull(busiData.get("costDept")).equals("")){
                costDeptId2 = EmptyUtil.checkNull(busiData.get("costDept"));
            }
            String costDeptId = costDeptId2;

            //通过部门获取部门负责人
            String deptManager = sysBaseAPI.getDeptManagerById(costDeptId);

            List<LoginUser> collect = allUser.stream().filter(u -> u.getId().equals(deptManager)).collect(Collectors.toList());
            users.addAll(collect);
        }
        // 发起人部门分管领导
        if(actNodeService.hasChooseDepLeader(nodeId,procDefId)){
            List<LoginUser> allUser = actNodeService.queryAllUser();
            /*表单数据写入*/
            Map<String, Object> busiData = actBusinessService.getBusiData(tableId, tableName);
            //费用承担部门
            String costDeptId2 = "";
            if(!EmptyUtil.checkNull(busiData.get("paymentDeptId")).equals("")){
                costDeptId2 = EmptyUtil.checkNull(busiData.get("paymentDeptId"));
            }
            if(!EmptyUtil.checkNull(busiData.get("costDept")).equals("")){
                costDeptId2 = EmptyUtil.checkNull(busiData.get("costDept"));
            }
            String costDeptId = costDeptId2;

            //通过部门获取部门负责人
            String deptLeader = sysBaseAPI.getDeptLeaderById(costDeptId);

            List<LoginUser> collect = allUser.stream().filter(u -> u.getId().equals(deptLeader)).collect(Collectors.toList());
            users.addAll(collect);
        }
        // 组织总经理
        if(actNodeService.hasChoosePresident(nodeId,procDefId)){
            List<LoginUser> allUser = actNodeService.queryAllUser();
            /*表单数据写入*/
            Map<String, Object> busiData = actBusinessService.getBusiData(tableId, tableName);
            //费用承担组织
            String costOrgCode2 = "";
            if(!EmptyUtil.checkNull(busiData.get("paymentCcid")).equals("")){
                costOrgCode2 = EmptyUtil.checkNull(busiData.get("paymentCcid"));
            }
            if(!EmptyUtil.checkNull(busiData.get("costCompCodeId")).equals("")){
                costOrgCode2 = EmptyUtil.checkNull(busiData.get("costCompCodeId"));
            }
            if(!EmptyUtil.checkNull(busiData.get("costCompanyCodeId")).equals("")){
                costOrgCode2 = EmptyUtil.checkNull(busiData.get("costCompanyCodeId"));
            }
            if(!EmptyUtil.checkNull(busiData.get("costCompayCodeId")).equals("")){
                costOrgCode2 = EmptyUtil.checkNull(busiData.get("costCompayCodeId"));
            }
            String costOrgCode = costOrgCode2;

            List<LoginUser> collect = allUser.stream().filter(u -> EmptyUtil.checkNull(u.getOrgCode()).equals(costOrgCode) && EmptyUtil.checkNull(u.getPost()).equals("president")).collect(Collectors.toList());
            users.addAll(collect);
        }
        // 组织董事长
        if(actNodeService.hasChooseCeo(nodeId,procDefId)){
            List<LoginUser> allUser = actNodeService.queryAllUser();
            /*表单数据写入*/
            Map<String, Object> busiData = actBusinessService.getBusiData(tableId, tableName);
            //费用承担组织
            String costOrgCode2 = "";
            if(!EmptyUtil.checkNull(busiData.get("paymentCcid")).equals("")){
                costOrgCode2 = EmptyUtil.checkNull(busiData.get("paymentCcid"));
            }
            if(!EmptyUtil.checkNull(busiData.get("costCompCodeId")).equals("")){
                costOrgCode2 = EmptyUtil.checkNull(busiData.get("costCompCodeId"));
            }
            if(!EmptyUtil.checkNull(busiData.get("costCompanyCodeId")).equals("")){
                costOrgCode2 = EmptyUtil.checkNull(busiData.get("costCompanyCodeId"));
            }
            if(!EmptyUtil.checkNull(busiData.get("costCompayCodeId")).equals("")){
                costOrgCode2 = EmptyUtil.checkNull(busiData.get("costCompayCodeId"));
            }
            String costOrgCode = costOrgCode2;

            List<LoginUser> collect = allUser.stream().filter(u -> EmptyUtil.checkNull(u.getOrgCode()).equals(costOrgCode) && EmptyUtil.checkNull(u.getPost()).equals("laozong")).collect(Collectors.toList());
            users.addAll(collect);
        }

        // 组织副总经理
        if(actNodeService.hasChooseViceCeo(nodeId,procDefId)){
            List<LoginUser> allUser = actNodeService.queryAllUser();
            /*表单数据写入*/
            Map<String, Object> busiData = actBusinessService.getBusiData(tableId, tableName);
            //费用承担组织
            String costOrgCode2 = "";
            if(!EmptyUtil.checkNull(busiData.get("paymentCcid")).equals("")){
                costOrgCode2 = EmptyUtil.checkNull(busiData.get("paymentCcid"));
            }
            if(!EmptyUtil.checkNull(busiData.get("costCompCodeId")).equals("")){
                costOrgCode2 = EmptyUtil.checkNull(busiData.get("costCompCodeId"));
            }
            if(!EmptyUtil.checkNull(busiData.get("costCompanyCodeId")).equals("")){
                costOrgCode2 = EmptyUtil.checkNull(busiData.get("costCompanyCodeId"));
            }
            if(!EmptyUtil.checkNull(busiData.get("costCompayCodeId")).equals("")){
                costOrgCode2 = EmptyUtil.checkNull(busiData.get("costCompayCodeId"));
            }
            String costOrgCode = costOrgCode2;

            List<LoginUser> collect = allUser.stream().filter(u -> EmptyUtil.checkNull(u.getOrgCode()).equals(costOrgCode) && EmptyUtil.checkNull(u.getPost()).equals("fuzongjingli")).collect(Collectors.toList());
            users.addAll(collect);
        }

        // 组织总会计师
        if(actNodeService.hasChooseGeneralAccountant(nodeId,procDefId)){
            List<LoginUser> allUser = actNodeService.queryAllUser();
            /*表单数据写入*/
            Map<String, Object> busiData = actBusinessService.getBusiData(tableId, tableName);
            //费用承担组织
            String costOrgCode2 = "";
            if(!EmptyUtil.checkNull(busiData.get("paymentCcid")).equals("")){
                costOrgCode2 = EmptyUtil.checkNull(busiData.get("paymentCcid"));
            }
            if(!EmptyUtil.checkNull(busiData.get("costCompCodeId")).equals("")){
                costOrgCode2 = EmptyUtil.checkNull(busiData.get("costCompCodeId"));
            }
            if(!EmptyUtil.checkNull(busiData.get("costCompanyCodeId")).equals("")){
                costOrgCode2 = EmptyUtil.checkNull(busiData.get("costCompanyCodeId"));
            }
            if(!EmptyUtil.checkNull(busiData.get("costCompayCodeId")).equals("")){
                costOrgCode2 = EmptyUtil.checkNull(busiData.get("costCompayCodeId"));
            }
            String costOrgCode = costOrgCode2;

            List<LoginUser> collect = allUser.stream().filter(u -> EmptyUtil.checkNull(u.getOrgCode()).equals(costOrgCode) && EmptyUtil.checkNull(u.getPost()).equals("zongkuaijish")).collect(Collectors.toList());
            users.addAll(collect);
        }
        // 财务部领导
        if(actNodeService.hasFinanceLeader(nodeId,procDefId)){
            /*表单数据写入*/
            Map<String, Object> busiData = actBusinessService.getBusiData(tableId, tableName);
            //费用承担组织
            String costOrgCode2 = "";
            if(!EmptyUtil.checkNull(busiData.get("paymentCcid")).equals("")){
                costOrgCode2 = EmptyUtil.checkNull(busiData.get("paymentCcid"));
            }
            if(!EmptyUtil.checkNull(busiData.get("costCompCodeId")).equals("")){
                costOrgCode2 = EmptyUtil.checkNull(busiData.get("costCompCodeId"));
            }
            if(!EmptyUtil.checkNull(busiData.get("costCompanyCodeId")).equals("")){
                costOrgCode2 = EmptyUtil.checkNull(busiData.get("costCompanyCodeId"));
            }
            if(!EmptyUtil.checkNull(busiData.get("costCompayCodeId")).equals("")){
                costOrgCode2 = EmptyUtil.checkNull(busiData.get("costCompayCodeId"));
            }
            String costOrgCode = costOrgCode2;
            //获取组织中的财务部领导角色的人
            List<LoginUser> loginUsers = sysBaseAPI.getUsersByRoleAndOrgCode(costOrgCode,"1451375156062175234");
            users.addAll(loginUsers);
        }
        // 财务部
        if(actNodeService.hasFinance(nodeId,procDefId)){
            List<LoginUser> allUser = actNodeService.queryAllUser();
            /*表单数据写入*/
            Map<String, Object> busiData = actBusinessService.getBusiData(tableId, tableName);
            //费用承担组织
            String costOrgCode2 = "";
            if(!EmptyUtil.checkNull(busiData.get("paymentCcid")).equals("")){
                costOrgCode2 = EmptyUtil.checkNull(busiData.get("paymentCcid"));
            }
            if(!EmptyUtil.checkNull(busiData.get("costCompCodeId")).equals("")){
                costOrgCode2 = EmptyUtil.checkNull(busiData.get("costCompCodeId"));
            }
            if(!EmptyUtil.checkNull(busiData.get("costCompanyCodeId")).equals("")){
                costOrgCode2 = EmptyUtil.checkNull(busiData.get("costCompanyCodeId"));
            }
            if(!EmptyUtil.checkNull(busiData.get("costCompayCodeId")).equals("")){
                costOrgCode2 = EmptyUtil.checkNull(busiData.get("costCompayCodeId"));
            }
            String costOrgCode = costOrgCode2;
            //获取组织中的财务部角色的人
            List<LoginUser> loginUsers = sysBaseAPI.getUsersByRoleAndOrgCode(costOrgCode,"1451375118506377217");
            users.addAll(loginUsers);
        }

        // 综合部负责人
        if(actNodeService.hasComprehensiveDeptLeader(nodeId,procDefId)){
            List<LoginUser> allUser = actNodeService.queryAllUser();
            /*表单数据写入*/
            Map<String, Object> busiData = actBusinessService.getBusiData(tableId, tableName);
            //费用承担组织
            String costOrgCode2 = "";
            if(!EmptyUtil.checkNull(busiData.get("paymentCcid")).equals("")){
                costOrgCode2 = EmptyUtil.checkNull(busiData.get("paymentCcid"));
            }
            if(!EmptyUtil.checkNull(busiData.get("costCompCodeId")).equals("")){
                costOrgCode2 = EmptyUtil.checkNull(busiData.get("costCompCodeId"));
            }
            if(!EmptyUtil.checkNull(busiData.get("costCompanyCodeId")).equals("")){
                costOrgCode2 = EmptyUtil.checkNull(busiData.get("costCompanyCodeId"));
            }
            if(!EmptyUtil.checkNull(busiData.get("costCompayCodeId")).equals("")){
                costOrgCode2 = EmptyUtil.checkNull(busiData.get("costCompayCodeId"));
            }
            String costOrgCode = costOrgCode2;

            //获取组织中的综合部门的负责人
            List<LoginUser> loginUsers = sysBaseAPI.getComprehensiveDeptLeaderByOrgCode(costOrgCode);
            users.addAll(loginUsers);
        }
        // 发起人
        if(actNodeService.hasChooseSponsor(nodeId,procDefId)){
            String createBy = getCreateBy(tableName,tableId);
            LoginUser userByName = sysBaseAPI.getUserById(createBy);
            users.add(userByName);
        }
        // 表单变量
        if(actNodeService.hasFormVariable(nodeId,procDefId)){
            List<String> variableNames = actNodeService.findFormVariableByNodeId(nodeId,procDefId);
            if(!variableNames.isEmpty()){
                Map<String, Object> applyForm = actBusinessService.getApplyForm(tableId, tableName);
                for(String variable : variableNames){
                    // 变量类型
                    String type = "user";
                    String paramName = variable;

                    int i = variable.indexOf(":");
                    if(i>0){
                        type = variable.substring(i + 1);
                        paramName = variable.substring(0,i);
                    }
                    // 获取表单变量的值
                    String paramVal = (String)applyForm.get(paramName);

                    if(StringUtils.isNotEmpty(paramVal)){
                        for(String val : StringUtils.split(paramVal,',')) {
                            if(StringUtils.equalsIgnoreCase(type,"role")){
                                List<LoginUser> roleUsers = actNodeService.findUserByRoleId(val);
                                users.addAll(roleUsers);
                            }else if(StringUtils.equalsIgnoreCase(type,"user")){
                                LoginUser user = sysBaseAPI.getUserByName(val);
                                if(user!=null){
                                    users.add(user);
                                }
                            }else if(StringUtils.equalsIgnoreCase(type,"dept")){
                                List<LoginUser> depUsers = actNodeService.findUserDepartmentId(val);
                                users.addAll(depUsers);
                            }else if(StringUtils.equalsIgnoreCase(type,"deptManage")){
                                List<LoginUser> depManageUsers = actNodeService.findUserDepartmentManageId(val);
                                users.addAll(depManageUsers);
                            }
                        }

                    }


                }
            }
        }

        // 过滤掉删除用户
        users = users.stream().filter(u->StrUtil.equals("0",u.getDelFlag()+"")).collect(Collectors.toList());
        return users;
    }

    /**
     * 根据节点id获取申请人
     * @param nodeId
     * @return
     */
    public String getUserByNodeid(String nodeId) {
        ActNode actNode = actNodeService.getOne(new LambdaQueryWrapper<ActNode>().eq(ActNode::getNodeId, nodeId).last("limit 1"));
        String procDefId = actNode.getProcDefId();
        ActBusiness actBusiness = actBusinessService.getOne(new LambdaQueryWrapper<ActBusiness>().eq(ActBusiness::getProcDefId, procDefId).last("limit 1"));
        return actBusiness.getCreateBy();
    }

    /**
     * 获取表单的创建人
     * @param tableName
     * @param tableId
     * @return
     */
    public String getCreateBy(String tableName,String tableId) {
        Map<String, Object> applyForm = actBusinessService.getApplyForm(tableId, tableName);
        return applyForm.get("createBy").toString();
    }

    /**
     * 获取表单的报销人
     * @param tableName
     * @param tableId
     * @return
     */
    public String getCostBy(String tableName,String tableId) {
        Map<String, Object> applyForm = actBusinessService.getCostApplyForm(tableId, tableName);
        return applyForm.get("createBy").toString();
    }

    /**
     * 去重
     * @param list
     * @return
     */
    private List<LoginUser> removeDuplicate(List<LoginUser> list) {

        LinkedHashSet<LoginUser> set = new LinkedHashSet<>(list.size());
        set.addAll(list);
        list.clear();
        list.addAll(set);
        entityManager.clear();
        list.forEach(u -> {
            u.setPassword(null);
        });
        return list;
    }

    public ProcessNodeVo getFirstNode(String procDefId,String tableName,String tableId) {
        BpmnModel bpmnModel = repositoryService.getBpmnModel(procDefId);

        ProcessNodeVo node = new ProcessNodeVo();

        List<Process> processes = bpmnModel.getProcesses();
        Collection<FlowElement> elements = processes.get(0).getFlowElements();
        // 流程开始节点
        StartEvent startEvent = null;
        for (FlowElement element : elements) {
            if (element instanceof StartEvent) {
                startEvent = (StartEvent) element;
                break;
            }
        }
        FlowElement e = null;
        // 判断开始后的流向节点
        SequenceFlow sequenceFlow = startEvent.getOutgoingFlows().get(0);
        for (FlowElement element : elements) {
            if(element.getId().equals(sequenceFlow.getTargetRef())){
                if(element instanceof UserTask){
                    e = element;
                    node.setType(1);
                    break;
                }else if(element instanceof ExclusiveGateway){
                    e = element;
                    node.setType(3);
                    break;
                }else if(element instanceof ParallelGateway){
                    e = element;
                    node.setType(4);
                    break;
                }else{
                    throw new RuntimeException("流程设计错误，开始节点后只能是用户任务节点、排他网关、并行网关");
                }
            }
        }
        // 排他、平行网关直接返回
        if(e instanceof ExclusiveGateway || e instanceof ParallelGateway){
            return node;
        }
        node.setTitle(e.getName());
        // 设置关联用户
        List<LoginUser> users = getNodetUsers(e.getId(),tableName,tableId,procDefId);
        node.setUsers(removeDuplicate(users));
        return node;
    }

    public ProcessNodeVo getNextNode(String procDefId, String currActId,String procInsId) {
        // 根据流程实例id获取业务表单数据
        ActBusiness actBusiness = actBusinessService.getOne(new LambdaQueryWrapper<ActBusiness>().eq(ActBusiness::getProcInstId, procInsId));

        ProcessNodeVo node = new ProcessNodeVo();
        // 当前执行节点id
        ProcessDefinitionEntity dfe = (ProcessDefinitionEntity) ((RepositoryServiceImpl)repositoryService).getDeployedProcessDefinition(procDefId);
        // 获取所有节点
        List<ActivityImpl> activitiList = dfe.getActivities();
        // 判断出当前流程所处节点，根据路径获得下一个节点实例
        for(ActivityImpl activityImpl : activitiList){
            if (activityImpl.getId().equals(currActId)) {
                // 获取下一个节点
                List<PvmTransition> pvmTransitions = activityImpl.getOutgoingTransitions();

                PvmActivity pvmActivity = pvmTransitions.get(0).getDestination();

                String type = pvmActivity.getProperty("type").toString();
                if("userTask".equals(type)){
                    // 用户任务节点
                    node.setType(ActivitiConstant.NODE_TYPE_TASK);
                    node.setTitle(pvmActivity.getProperty("name").toString());
                    // 设置关联用户
                    List<LoginUser> users = getNodetUsers(pvmActivity.getId(),actBusiness.getTableName(),actBusiness.getTableId(),actBusiness.getProcDefId());
                    node.setUsers(removeDuplicate(users));
                }else if("exclusiveGateway".equals(type)){
                    // 排他网关
                    node.setType(ActivitiConstant.NODE_TYPE_EG);
                    ActivityImpl pvmActivity1 = (ActivityImpl) pvmActivity;
                    /*定义变量*/
                    Map<String, Object> vals = Maps.newHashMap();

                    LambdaQueryWrapper<ActBusiness> wrapper = new LambdaQueryWrapper<>();
                    wrapper.eq(ActBusiness::getProcInstId,procInsId);
                    ActBusiness one = actBusinessService.getOne(wrapper);
                    vals = actBusinessService.getApplyForm(one.getTableId(), one.getTableName());

                    TaskDefinition taskDefinition = actNodeService.nextTaskDefinition(pvmActivity1, pvmActivity1.getId(), vals, procInsId);
                    List<LoginUser> users = getNodetUsers(taskDefinition.getKey(),actBusiness.getTableName(),actBusiness.getTableId(),actBusiness.getProcDefId());
                    node.setUsers(removeDuplicate(users));
                }else if("parallelGateway".equals(type)){
                    // 平行网关
                    node.setType(ActivitiConstant.NODE_TYPE_PG);
                }else if("endEvent".equals(type)){
                    // 结束
                    node.setType(ActivitiConstant.NODE_TYPE_END);
                }else{
                    throw new JeecgBootException("流程设计错误，包含无法处理的节点");
                }
                break;
            }
        }

        return node;
    }

    @Override
    public List<ActZprocess> queryNewestProcess(String processKey) {
        return baseMapper.selectNewestProcess(processKey);
    }

    @Override
    public List<ActZProcessOrg> selectByProcessId(String id) {
        return actZprocessMapper.selectByProcessId(id);
    }

    public void updateTaskBack(String taskId) {
        actNodeService.updateTaskBack(taskId);
    }

    public void updateTaskCancel(String taskId) {
        actNodeService.updateTaskCancel(taskId);
    }

    public void reloadActivitiVariable(String tableName, String tableId, String workflowTaskId) {
        /*表单数据写入*/
        Map<String, Object> busiData = actBusinessService.getBusiData(tableId, tableName);
        //此对象作为流程变量（注意：POJO类型，一定要实现Serializable接口，否则在存储这个pojo时就会报异常）
        Map<String,Object> eaAmtMap = new HashMap<String,Object>();
        String userid = "e9ca23d68d884d4ebb19d07889727dae";   //报销人
        if(!EmptyUtil.checkNull(busiData.get("eaPersonId")).equals("")){
            userid = EmptyUtil.checkNull(busiData.get("eaPersonId"));
        }
        if(!EmptyUtil.checkNull(busiData.get("personId")).equals("")){
            userid = EmptyUtil.checkNull(busiData.get("personId"));
        }
        if(!EmptyUtil.checkNull(busiData.get("personalId")).equals("")){
            userid = EmptyUtil.checkNull(busiData.get("personalId"));
        }
        if(!EmptyUtil.checkNull(busiData.get("borrowerId")).equals("")){
            userid = EmptyUtil.checkNull(busiData.get("borrowerId"));
        }
        if(!EmptyUtil.checkNull(busiData.get("repayerId")).equals("")){
            userid = EmptyUtil.checkNull(busiData.get("repayerId"));
        }

        //要设置费用项目以及报销金额
        String indexId = EmptyUtil.checkNull(busiData.get("indexId"));    //费用项目

        BigDecimal actualPayAmt = new BigDecimal(0);    //实际付款金额
        if(busiData.get("actualPayAmt") != null){
            actualPayAmt = new BigDecimal(busiData.get("actualPayAmt").toString());
        }
        if(busiData.get("loan_amount") != null){
            actualPayAmt = new BigDecimal(busiData.get("loan_amount").toString());
        }

        //判断总经理审核还是董事长审核
        int needPresident = checkIsNeedPresidentAudit(indexId,actualPayAmt);
        int needCeo = checkIsNeedCeoAudit(indexId,actualPayAmt);
        int needCfo = 0; // 财务领导审批

        //费用承担部门
        String costDeptId2 = "";
        if(!EmptyUtil.checkNull(busiData.get("paymentDeptId")).equals("")){
            costDeptId2 = EmptyUtil.checkNull(busiData.get("paymentDeptId"));
        }
        if(!EmptyUtil.checkNull(busiData.get("costDept")).equals("")){
            costDeptId2 = EmptyUtil.checkNull(busiData.get("costDept"));
        }
        String costDeptId = costDeptId2;
        String costDeptName = sysBaseAPI.getDepartNameById(costDeptId);

        //判断是否高管
        int toDeptManager = 0;
        int toPresident = 0;
        int toCeo = 0;

        if(costDeptName.equals("总经理室")){  //总经理审批
            toPresident = 1;
        }else if(costDeptName.equals("董事长室") || costDeptName.equals("副总经理室") || costDeptName.equals("总会计师室")){  //董事长室,总会计师室,副总经理室
            toCeo = 1;
        }else{
            toDeptManager = 1;
        }

        // 差旅费报销单 高管审批节点判断 【如果总经理室、董事长室先走财务领导审批】
        if("ea_travel".equals(tableName)){
            // 通过部门名称判断走哪个节点
            if(costDeptName.equals("总经理室") || costDeptName.equals("董事长室")){  // 财务领导审批
                needCfo = 1;
            }else if(costDeptName.equals("副总经理室") || costDeptName.equals("总会计师室")){  //董事长室,总会计师室,副总经理室
                toCeo = 1;
            }else{
                toDeptManager = 1;
            }
        }

        if("ea_travel".equals(tableName) && needCfo == 1){
            if(costDeptName.equals("总经理室")){  //总经理审批
                needPresident = 1;
            }else if(costDeptName.equals("董事长室")){  //董事长室,总会计师室,副总经理室
                needCeo = 1;
            }
        }

//        LoginUser loginUser1 = sysBaseAPI.getUserById(userid);
        LoginUser loginUser1 = sysBaseAPI.getLoginUserByPkpsndoc(userid);
        eaAmtMap.put("identity",loginUser1.getUserIdentity());
        taskService.setVariable(workflowTaskId,"user",eaAmtMap);               //用户信息(是否上级)
        taskService.setVariable(workflowTaskId,"needPresident",needPresident); //是否需要总经理审批
        taskService.setVariable(workflowTaskId,"needCeo",needCeo);             //是否需要董事长审批
        taskService.setVariable(workflowTaskId,"toDeptManager",toDeptManager); //部门负责人审批
        taskService.setVariable(workflowTaskId,"toPresident",toPresident);     //总经理审批(高管流程)
        taskService.setVariable(workflowTaskId,"toCeo",toCeo);                 //董事长审批(高管流程)
        taskService.setVariable(workflowTaskId,"costDeptName",costDeptName);   //费用承担部门
        taskService.setVariable(workflowTaskId,"amt",actualPayAmt);            //实际报销金额
        taskService.setVariable(workflowTaskId,"needCfo",needCfo);            //财务领导审批
    }


    @Override
    public void pass(String taskId, String procInstId,String procDefId, String assignees, Integer priority, String comment, Boolean sendMessage, Boolean sendSms, Boolean sendEmail) {
        if(StrUtil.isBlank(comment)){
            comment = "";
        }
        taskService.addComment(taskId, procInstId, comment);
        ProcessInstance pi = runtimeService.createProcessInstanceQuery().processInstanceId(procInstId).singleResult();
        Task task = taskService.createTaskQuery().taskId(taskId).singleResult();
        if(StrUtil.isNotBlank(task.getOwner())&&!("RESOLVED").equals(task.getDelegationState().toString())){
            // 未解决的委托任务 先resolve
            String oldAssignee = task.getAssignee();
            taskService.resolveTask(taskId);
            taskService.setAssignee(taskId, oldAssignee);
        }

        /**
         * 修改流程表单变量
         * 表单参数
         */
        LambdaQueryWrapper<ActBusiness> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(ActBusiness::getProcInstId,pi.getProcessInstanceId());
        ActBusiness one = actBusinessService.getOne(queryWrapper);
        Map<String, Object> busiData = actBusinessService.getBusiData(one.getTableId(), one.getTableName());

        /**
         * 获取所有流程变量 并修改
         */
        for(String key : busiData.keySet()){
            taskService.setVariable(taskId,key,busiData.get(key));
        }

        /*会签思路：
        act_hi_identitylink记录着审批历史 ActivitiConstant.EXECUTOR_TYPE_p 标识审批通过
        1、节点设置中增加人数字段，表示需要多少人通过这个任务节点才通过
        2、此处查询审批历史，查看当前节点的审批情况，符合预设的人数调用 taskService.complete(id); 完成该节点任务
        +



        否则只记录审批数据，不完成该任务节点
        3、会有的问题：
            1、如此，审批过的人代办中还会看到这条任务，需要标识自己审批过，但是这条任务自己不能再审了  或 能再审，但是再审记得把之前审批过的记录删掉
            2、下一个节点的审批人只能最后通过的人选择才有效
            3、如果下一个节点是会签，指定下一节点的审批人的数量必须不小于节点预设数量
            其他问题，待暴露
          */
        /*完成任务*/
        taskService.complete(taskId);
        ActBusiness actBusiness = actBusinessService.getById(pi.getBusinessKey());
        //修改业务表的流程字段
        actBusinessService.updateBusinessStatus(actBusiness.getTableName(), actBusiness.getTableId(),"审批中-"+task.getTaskDefinitionKey()+"-"+task.getName());

        task.getName();
        LoginUser loginUser = (LoginUser) SecurityUtils.getSubject().getPrincipal();
        List<Task> tasks = taskService.createTaskQuery().processInstanceId(procInstId).list();
        // 判断下一个节点
        if(tasks!=null&&tasks.size()>0){
            for(Task t : tasks){
                if(StrUtil.isBlank(assignees)){
                    // 如果下个节点未分配审批人为空 取消结束流程
                    List<LoginUser> users = this.getNode(t.getTaskDefinitionKey(),actBusiness.getTableName(),actBusiness.getTableId(),procDefId).getUsers();
                    if(users==null||users.size()==0){
                        runtimeService.deleteProcessInstance(procInstId, "canceled-审批节点未分配审批人，流程自动中断取消");
                        actBusiness.setStatus(ActivitiConstant.STATUS_CANCELED);
                        actBusiness.setResult(ActivitiConstant.RESULT_TO_SUBMIT);
                        actBusinessService.updateById(actBusiness);
                        //修改业务表的流程字段
                        actBusinessService.updateBusinessStatus(actBusiness.getTableName(), actBusiness.getTableId(),"审批异常-"+task.getTaskDefinitionKey()+"-"+task.getName()+"-审批节点未分配审批人，流程自动中断取消");

                        break;
                    }else{
                        // 避免重复添加
                        List<String> list = actBusinessService.selectIRunIdentity(t.getId(), ActivitiConstant.EXECUTOR_candidate);
                        if(list==null||list.size()==0) {
                            // 分配了节点负责人分发给全部
                            for (LoginUser user : users) {
                                taskService.addCandidateUser(t.getId(), user.getUsername());
                                // 异步发消息
                                this.sendActMessage(loginUser,user,actBusiness,task.getName(),  sendMessage, sendSms, sendEmail);
                            }
                            taskService.setPriority(t.getId(), task.getPriority());
                        }
                    }
                }else{
                    // 避免重复添加
                    List<String> list = actBusinessService.selectIRunIdentity(t.getId(), ActivitiConstant.EXECUTOR_candidate);
                    if(list==null||list.size()==0) {

                        for(String assignee : assignees.split(",")){
                            taskService.addCandidateUser(t.getId(), assignee);
                            // 异步发消息
                            LoginUser user = sysBaseAPI.getUserByName(assignee);
                            this.sendActMessage(loginUser,user,actBusiness,task.getName(),  sendMessage, sendSms, sendEmail);
                            taskService.setPriority(t.getId(), priority);
                        }
                    }
                }
            }
        } else {
            actBusiness.setStatus(ActivitiConstant.STATUS_FINISH);
            actBusiness.setResult(ActivitiConstant.RESULT_PASS);
            actBusinessService.updateById(actBusiness);
            // 异步发消息
            LoginUser user = sysBaseAPI.getUserByName(actBusiness.getUserId());
            this.sendMessage(actBusiness.getId(),loginUser,user,ActivitiConstant.MESSAGE_PASS_CONTENT,
                    String.format("您的 【%s】 申请已通过！",actBusiness.getTitle()),sendMessage, sendSms, sendEmail);
            //修改业务表的流程字段
            actBusinessService.updateBusinessStatus(actBusiness.getTableName(), actBusiness.getTableId(),"审批通过");

        }
        // 记录实际审批人员
        actBusinessService.insertHI_IDENTITYLINK(IdUtil.simpleUUID(),
                ActivitiConstant.EXECUTOR_TYPE_p, loginUser.getUsername(), taskId, procInstId);

    }
}
